package com.sky.service.admin.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.exception.ParameterIsNullException;
import com.sky.mapper.user.OrderMapper;
import com.sky.mapper.user.UserMapper;
import com.sky.pojo.Orders;
import com.sky.service.admin.ReportService;
import com.sky.service.admin.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ReportServiceImpl implements ReportService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private WorkspaceService workspaceService;

    /**
     * 根据时间区间统计营业额
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        //参数判断
        if (begin == null || end == null) {
            throw new ParameterIsNullException("参数异常");
        }
        //指定时间段之内的每一天的销售额
        /**
         *  2种做法：
         *    第一种做法：简单， 循环，一天一天的查询
         *    第二种做法：复杂，一条sql语句查询出来
         */
        //日期集合
        List<String> dataList = new ArrayList<>();
        //销售总额集合
        List<Double> turnoverList = new ArrayList<>();
        //获取日期集合
        while (begin.isBefore(end)) {
            dataList.add(begin.toString());
            //都要查询当天的数据
            Double salesVolume = orderMapper.selectSalesByDay(begin.toString());
            if (salesVolume == null) {
                salesVolume = 0.0;//当天查询到的数据，重置为0
            }
            turnoverList.add(salesVolume);
            //begin往后数天(天数加一begin+1)
            begin = begin.plusDays(1);
        }
        //封装数据返回
        String dateList = StringUtils.join(dataList, ",");
        String turnoverListStr = StringUtils.join(turnoverList, ",");
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setDateList(dateList);
        turnoverReportVO.setTurnoverList(turnoverListStr);
        return turnoverReportVO;
        /**
         * String dateList = StringUtils.join(dataList, ",");
         * StringUtils：这通常是 Apache Commons Lang 库中的工具类，提供了许多处理字符串的实用方法。
         * join 方法用于将集合（如列表）中的元素连接成一个字符串。
         * dataList：这是一个包含多个元素的列表，列表中的元素可以是任意类型，不过在连接时会调用元素的 toString()
         * 方法将其转换为字符串。
         * ","：这是连接符，表示在连接列表元素时，每个元素之间用逗号分隔。
         * 执行结果：将 dataList 中的元素用逗号连接成一个字符串，并将该字符串赋值给变量 dateList。
         * 例如，如果 dataList 是 ["2023-01-01", "2023-01-02", "2023-01-03"]，那么 dateList
         * 的值将是 "2023-01-01,2023-01-02,2023-01-03"。
         * */
    }

    /**
     * 用户统计
     */
    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        //参数判断
        if (begin == null || end == null) {
            throw new ParameterIsNullException("参数异常");
        }
        //获取日期集合
        List<String> dataList = new ArrayList<>();
        //用户总数集合
        List<Integer> totalUserList = new ArrayList<>();
        //新增用户集合
        List<Integer> newUserList = new ArrayList<>();
        while (begin.isBefore(end)) {
            dataList.add(begin.toString());
            //根据时间段查询每日的用户新增数量
            Integer newUser = userMapper.countNewUserByDate(begin.toString());
            if (newUser == null) {
                newUser = 0;
            }
            newUserList.add(newUser);
            begin = begin.plusDays(1);
        }
        //查询起始时间之前的所有用户数量
        Integer totalUser = userMapper.countUserByDate(begin.toString());
        //每天的用户总数=总用户数+新增用户数
        totalUser = totalUser == null ? 0 : totalUser;
        for (Integer integer : newUserList) {
            totalUser += integer;
            totalUserList.add(totalUser);
        }
        //封装数据返回
        String dateList = StringUtils.join(dataList, ",");
        String totalUserListStr = StringUtils.join(totalUserList, ",");
        String newUserListStr = StringUtils.join(newUserList, ",");
        UserReportVO userReportVO = new UserReportVO();
        userReportVO.setDateList(dateList);
        userReportVO.setTotalUserList(totalUserListStr);
        userReportVO.setNewUserList(newUserListStr);
        return userReportVO;

    }

    /**
     * 订单统计
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        String beginStr = begin.toString();
        String endStr = end.toString();
        //日期集合
        List<String> dateList = new ArrayList<>();
        //每日订单总数
        List<Integer> orderCountList = new ArrayList<>();
        //每日有效订单数
        List<Integer> validOrderCountList = new ArrayList<>();
        end = end.plusDays(1);
        while (begin.isBefore(end)) {
            dateList.add(begin.toString());
            begin = begin.plusDays(1);
        }
        //1. 指定时间段内的所有订单数
        int allTotal = orderMapper.selectOrdersByDateAndStatus(beginStr, endStr, null);
        //2.指定时间段内的有效订单数
        int completedTotal = orderMapper.selectOrdersByDateAndStatus(beginStr, endStr, Orders.COMPLETE_ORDER);
        //3.订单完成率
        double orderCompletionRate = completedTotal * 1.0 / allTotal;
        //4.指定时间段内的每日的订单总数
        Map<String, Long> res1 = orderMapper.selectEveryDayOrderCountByDateAndStatus(beginStr, endStr, null, dateList);
        //5.指定时间段内的每日有效订单数
        Map<String, Long> res2 = orderMapper.selectEveryDayOrderCountByDateAndStatus(beginStr, endStr, Orders.COMPLETE_ORDER, dateList);
        dateList.forEach(date -> {
            orderCountList.add(res1.get(date).intValue());
            validOrderCountList.add(res2.get(date).intValue());
        });
        //组装数据
        String dateListStr = StringUtils.join(dateList, ",");
        String orderCountListStr = StringUtils.join(orderCountList, ",");
        String validOrderCountListStr = StringUtils.join(validOrderCountList, ",");
        OrderReportVO orderReportVO = new OrderReportVO();
        orderReportVO.setDateList(dateListStr);
        orderReportVO.setOrderCountList(orderCountListStr);
        orderReportVO.setValidOrderCountList(validOrderCountListStr);
        orderReportVO.setTotalOrderCount(allTotal);
        orderReportVO.setValidOrderCount(completedTotal);
        orderReportVO.setOrderCompletionRate(orderCompletionRate);
        return orderReportVO;
    }

    /**
     * 销量排名Top10
     */
    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        //参数判断
        if (begin == null || end == null) {
            throw new ParameterIsNullException("参数异常");
        }
        //查询销量top10的数据
        List<GoodsSalesDTO> salesTop10 = orderMapper.getSalesTop10(begin.toString(), end.toString());
        //封装数据
        List<String> nameList = new ArrayList<>();
        List<Long> numberList = new ArrayList<>();
        //遍历集合
        salesTop10.forEach(goodsSalesDTO -> {
            nameList.add(goodsSalesDTO.getName());
            numberList.add(goodsSalesDTO.getNumber());
        });
        //封装数据
        String nameListStr = StringUtils.join(nameList, ",");
        String numberListStr = StringUtils.join(numberList, ",");
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        salesTop10ReportVO.setNameList(nameListStr);
        salesTop10ReportVO.setNumberList(numberListStr);
        return salesTop10ReportVO;
    }

    /**
     * 导出运营数据报表
     *
     * @param response
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        //获取近30天的运营数据
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);
        //查询概览运营数据，提供Excel模板
        BusinessDataVO businessData = workspaceService.getBusinessDate(begin, end);
        BusinessDataVO business = workspaceService.BusinessDate(begin, end);
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表.xlsx");
        try {
            //基于提供好的模板文件创建一个新的Excel表格对象
            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
            //获取Excel文件中的一个Sheet表格对象
            XSSFSheet sheet = excel.getSheet("Sheet1");
            sheet.getRow(1).getCell(1).setCellValue(begin + "至" + end);
            //获取第4行，设置日期数据
            XSSFRow row = sheet.getRow(3);
            //获取单元格
            row.getCell(2).setCellValue(business.getTurnover());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(6).setCellValue(business.getNewUsers());
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessData.getValidOrderCount());
            row.getCell(4).setCellValue(businessData.getUnitPrice());
            for (int i = 0; i < 30; i++) {
                LocalDate date = begin.plusDays(i);
                //准备明细数据
                businessData = workspaceService.getBusinessDate(date, date);
                row = sheet.getRow(7 + i);
                row.getCell(1).setCellValue(date.toString());
                row.getCell(2).setCellValue(businessData.getTurnover());
                row.getCell(3).setCellValue(businessData.getValidOrderCount());
                row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessData.getUnitPrice());
                row.getCell(6).setCellValue(businessData.getNewUsers());
            }
            //通过输出流将文件下载到客户端浏览器中
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);
            //关闭资源
            out.flush();
            out.close();
            excel.close();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}
